package com.kx.file.controller;

import com.alibaba.fastjson.JSONObject;
import com.kx.base.dto.file.ImgDTO;
import com.kx.base.dto.file.PathDTO;
import com.kx.base.dto.file.QRCodeDTO;
import com.kx.base.dto.file.ZoomDTO;
import com.kx.base.result.R;
import com.kx.base.util.AsyncBatchCallUtil;
import com.kx.base.util.FileBase64Util;
import com.kx.base.util.ImageUtil;
import com.kx.file.pojo.GifWork;
import com.kx.file.service.GifService;
import com.kx.file.util.AlibabaOSSUtil;
import com.kx.file.util.QRCodeUtil;
import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;

/**
 * 文件存储的controller
 *
 * @Author Sun
 * @Date 2021/7/22 19:09
 */
@RestController
@RequestMapping("kx/file")
public class FileController {

    @Autowired
    private GifService gifService;

    /**
     * 这是临时目录，如果是linux得该这个目录
     */
    public static final String FILE_PATH = "D:\\TEMP";

    /**
     * 上传图片的接口
     */
    @PostMapping("img")
    public R uploadImage(@RequestBody ImgDTO imgDTO) {
        String base64 = imgDTO.getBase64();
        //文件名使用uuid
        String fileName = UUID.randomUUID().toString().replaceAll("-", "");
        //思路1：把Base64还原成文件，然后再上传给ali云，然后再删除，总共三次IO
        File file = FileBase64Util.base642File(base64, fileName);
        //把本地文件交给阿里云服务器
//        String url = AlibabaOSSUtil.uploadFile(fileName, file);
        //临时文件已经没有用了，就删除
//        file.delete();
        //思路2：我们拿到了代表文件数据的base64，此时文件数据就在我们的内存中，如何直接给阿里云呢？
        //阿里云要的参数可以是文件，也可以是流。
        //也就是说，我们需要把内存数据以流的形式给阿里云，
        //这个流就是由内存流向内存。
        byte[] bytes = Base64.decodeBase64(base64);
        ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
        String url = AlibabaOSSUtil.uploadFile(fileName, bis);
        JSONObject result = new JSONObject();
        result.put("url", url);
        return R.ok(result, 200, "上传成功");
    }

    /**
     * 上传视频的接口
     */
    @PostMapping("mp4")
    public R uploadMP4(MultipartFile file) {
        //生成文件名
        String fileName = UUID.randomUUID().toString().replaceAll("-", "") + ".mp4";
        InputStream inputStream = null;
        try {
            inputStream = file.getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
        String url = AlibabaOSSUtil.uploadFile(fileName, inputStream);
        JSONObject result = new JSONObject();
        result.put("url", url);
        return R.ok().setResult(result);
    }

    /**
     * 这个是一个上传mp4文件自动生成gif预览与jpg封面的接口
     * 这是一个高耗时的接口。
     * 采用异步设计：与同步设计相对应，同步设计是接口被请求了以后
     * 秒级立刻就能响应处理的结果。异步设计就是接口被请求以后，立即
     * 返回接口调用成功，后台任务正在执行。
     * 使用线程池实现异步请求
     * 然后还有一个查询任务的接口，你可以查询之前的后台任务是否执行完毕。
     */
    @PostMapping("gif")
    public R uploadMP4File(MultipartFile file) throws IOException {
        //生成文件名
        String fileName = UUID.randomUUID().toString().replaceAll("-", "") + ".mp4";
        //实例化临时目录的文件
        File targetFile = new File(FILE_PATH + File.separator + fileName);
        //写入到目标文件
        file.transferTo(targetFile);
        //保存至OSS文件服务器
        String url = AlibabaOSSUtil.uploadFile(fileName, targetFile);
        //希望能本地保存一份文件，进而生成gif与jpg，然后也上传至OSS

        //创建了一个任务
        gifService.addGifWork(url);

        //这个方法是一个高耗时操作，等这个方法完事了，http早就超时了。
        //异步开启后台任务
//        new Thread(new Runnable() {
//            @Override
//            public void run() {
//                gifService.createGif(targetFile,fileName,url);
//            }
//        }).start();

        //使用封装好的线程池执行我们的异步逻辑
        AsyncBatchCallUtil.execute(() -> gifService.createGif(targetFile, fileName, url));

        JSONObject result = new JSONObject();
        result.put("url", url);
        return R.ok().setResult(result);
    }

    /**
     * 查询gif与jpg生成情况的方法
     */
    @PostMapping("search")
    public R searchWork(@RequestBody PathDTO pathDTO) {
        String url = pathDTO.getUrl();

        //查询数据库
        GifWork gifWork = gifService.selectByVideoUrl(url);
        //返回结果
        if (gifWork.getState() == 0) {
            return R.ok("gif正在生成").setResult(gifWork);
        } else if (gifWork.getState() == 1) {
            return R.ok(201, "gif生成完毕").setResult(gifWork);
        } else {
            return R.error(500, "gif生成失败").setResult(gifWork);
        }
    }

    /**
     * 图片上传
     * 放缩图片以及添加水印
     */
    @PostMapping("zoom")
    public R uploadZoomImage(@RequestBody ZoomDTO zoomDTO) {
        String base64 = zoomDTO.getBase64();
        int width = zoomDTO.getWidth();
        int height = zoomDTO.getHeight();
        String title = zoomDTO.getTitle();

        BufferedImage bufferedImage = FileBase64Util.base642Image(base64);
        bufferedImage = ImageUtil.zoom(bufferedImage, width, height, title);
        //bufferedImage->byte[]->内存流
        base64 = FileBase64Util.image2Base64(bufferedImage);
        byte[] bytes = Base64.decodeBase64(base64);
        ByteArrayInputStream bais = new ByteArrayInputStream(bytes);

        //存阿里云上
        String fileName = UUID.randomUUID().toString().replaceAll("-", "") + ".jpg";
        String url = AlibabaOSSUtil.uploadFile(fileName, bais);
        JSONObject result = new JSONObject();
        result.put("url", url);
        return R.ok().setResult(result);
    }

    /**
     * 生成二维码的接口
     */
    @PostMapping("qrCode")
    public R qrCode(@RequestBody QRCodeDTO qrCodeDTO) {
        String content = qrCodeDTO.getContent();
        Integer width = qrCodeDTO.getWidth();
        Integer height = qrCodeDTO.getHeight();
        //前端传过来的颜色为"#ffffff"，但是后台使用的颜色为0xffffffff，前两位是是否透明
        String codeColorStr = qrCodeDTO.getCodeColor().replace("#", "");
        Integer codeColor = Integer.parseInt(codeColorStr, 16) | 0xff << 24;
        String bgColorStr = qrCodeDTO.getBgColor().replace("#", "");
        Integer bgColor = Integer.parseInt(bgColorStr, 16) | 0xff << 24;

        //生成二维码图片
        BufferedImage bufferedImage = QRCodeUtil.qrEncode(content, codeColor, bgColor, width, height);

        //将图片编码成base64
        String base64 = FileBase64Util.image2Base64(bufferedImage);

        JSONObject result = new JSONObject();
        result.put("qrCode", base64);
        return R.ok("二维码生成成功").setResult(result);
    }
}
